package com.tianji.learning.task;

import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.utils.InfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;

import static com.tianji.common.constants.RedisConstants.POINT_BOARD_KEY_PREFIX;
import static com.tianji.common.utils.DateUtils.DATE_SUFFIX_FORMATTER;
import static com.tianji.learning.constants.Constants.POINTS_BOARD_TABLE_PREFIX;


/**
 * 持久化历史积分排行榜数据定时任务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PointBoardTableTask {
    private final IPointsBoardSeasonService seasonService;
    private final IPointsBoardService boardService;
    private final StringRedisTemplate redisTemplate;
    //定义上月排行榜key
    private final String key = POINT_BOARD_KEY_PREFIX + DateUtils.format(DateUtils.now().minusMonths(1), DATE_SUFFIX_FORMATTER);


    /**
     * 任务一、创建对应赛季的积分排行榜表
     */
    @XxlJob("createTableJob")
    public void createPointsBoardTable() {
        //1、查询上月赛季Id
        Integer seasonId = seasonService.querySeasonIdByDate(DateUtils.now().minusMonths(1));

        //2、根据赛季Id创建新表名，通过mapper执行建表语句
        boardService.createPointsBoardTable(seasonId);
    }

    /**
     * 任务二、从redis中读取上月排行榜数据持久化至mysql
     */
    @XxlJob("savePointsBoard2DB")
    public void readPointsBoardAndSyncToMysql() {
        //1、从redis 中读取上月排行榜数据

        //xxljob分片模式参数
        int shardIndex = XxlJobHelper.getShardIndex();//当前服务分片序号
        int shardTotal = XxlJobHelper.getShardTotal();//该服务总分片数量
        //1.1定义分页数据
        int pageNo = shardIndex + 1;
        int pageSize = 4;
        //0、执行同步操作时，需要计算组装新表名存入threadLocal中
        String tableName = POINTS_BOARD_TABLE_PREFIX + seasonService.querySeasonIdByDate(DateUtils.now().minusMonths(1));
        InfoContext.setInfo(tableName);
        while (true) {
            //1.2调用service的查询当前赛季排行榜方法（参数为修改了的上月key）
            List<PointsBoard> boardList = boardService.queryCurrentBoardList(key, pageNo, pageSize);
            if (ObjectUtils.isEmpty(boardList)) {
                break;
            }
            //2、处理boardList
            boardList.forEach(board -> {
                board.setId(Long.valueOf(board.getRank()));
                board.setRank(null);
                board.setSeason(null);
            });
            //3、批量保存至Mysql
            boardService.saveBatch(boardList);
            //4、翻页
            pageNo += shardTotal;
        }
        //5、向thredLocal中存入了数据，务必再使用完之后使用remove（）删除
        InfoContext.removeInfo();
    }


    /**
     * 任务三、将redis中的排行榜数据删除
     */
    @XxlJob("clearPointsBoardFromRedis")
    public void removePointsBoardDataFromRedis() throws InterruptedException {
        Thread.sleep(10000);
        redisTemplate.unlink(key);
    }
}
